package com.manager.common.token;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.RemovalCause;
import com.github.benmanes.caffeine.cache.RemovalListener;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

public class TokenManager {

    private String tokenName;

    private static TokenManager tokenManager = new TokenManager();

    public static Cache<String, TokenInfo> tokenCaffeine;

    private Logger logger = LoggerFactory.getLogger(TokenManager.class);

    public static Cache<String, String> dowloadTokenCaffeine = Caffeine.newBuilder()
            .expireAfterAccess(10, TimeUnit.SECONDS)
            .removalListener(new RemovalListener<String, String>() {
                @Override
                public void onRemoval(@Nullable String key, @Nullable String value, @NonNull RemovalCause cause) {
                    System.out.println("下载token失效！");
                }
            })
            .build();

    private static Map<String, Object> dataMap = new ConcurrentHashMap<>();


    private TokenManager() {

    }

    public static TokenManager getInstance() {
        return tokenManager;
    }

    public void init(String tokenName, int tokenPeriodTime) {
        this.tokenName = tokenName;
        if (tokenCaffeine != null) {
            return;
        }
        synchronized (TokenManager.class) {
            if (tokenCaffeine != null) {
                return;
            }
            tokenCaffeine = Caffeine.newBuilder()
                    .expireAfterAccess(tokenPeriodTime, TimeUnit.MINUTES)
                    .removalListener(new RemovalListener<String, Object>() {
                        @Override
                        public void onRemoval(@Nullable String key, @Nullable Object value, @NonNull RemovalCause cause) {
                            logger.info("过期登出key: " + key);
                        }
                    })
                    .build();
        }
    }

    public TokenInfo login(String id) throws Exception {

        TokenInfo tokenInfo = new TokenInfo();
        tokenInfo.setTokenName(tokenName);
        tokenInfo.setTokenValue(RASUtils.encrypt(id));
        tokenCaffeine.put(id, tokenInfo);

        return tokenInfo;
    }

    public void logout(String token) {
        tokenCaffeine.invalidate(token);
    }

    public <T> T get(String token) {
        if (StringUtils.isBlank(token)) {
            return null;
        }
        TokenInfo tokenInfo = tokenCaffeine.getIfPresent(token);
        if (tokenInfo == null) {
            return null;
        }
        return (T) tokenInfo.getData();
    }

    public TokenInfo login(String id, Object data) throws Exception {

        TokenInfo tokenInfo = new TokenInfo();
        tokenInfo.setTokenName(tokenName);
        tokenInfo.setTokenValue(RASUtils.encrypt(id));
        tokenInfo.setData(data);
        tokenCaffeine.put(tokenInfo.getTokenValue(), tokenInfo);

        return tokenInfo;
    }
    public boolean checkLoginByToken(String token) {
        if (StringUtils.isEmpty(token)) {
            return false;
        }
        return tokenCaffeine.getIfPresent(token) != null;
    }

    public boolean isLogin() {
        String token = TokenUtils.getCurrentToken();
        return checkLoginByToken(token);
    }

    public String generateDownloadToken() throws Exception {
        String token = RASUtils.encrypt(UUID.randomUUID().toString().replaceAll("-",""));
        dowloadTokenCaffeine.put(token, "1");
       return  token;
    }

    public boolean hasDownloadToken(String token) {
       boolean has =  dowloadTokenCaffeine.getIfPresent(token) != null;
       System.out.println("校验下载token: " + has);
       dowloadTokenCaffeine.invalidate(token);
       return has;
    }

    public String getTokenName() {
        return tokenName;
    }

    public static void main(String[] args) throws Exception{
        System.out.println(TokenManager.getInstance().generateDownloadToken());
    }
}
